// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only

using System;
using System.Collections.Generic;
using System.Linq;
using FluentAssertions;
using Nethermind.Core;
using Nethermind.Core.Collections;
using Nethermind.Core.Extensions;
using Nethermind.Int256;
using Nethermind.Optimism.CL.Decoding;
using NUnit.Framework;

namespace Nethermind.Optimism.Test.CL;

public class BatchDecoderTests
{
    [Test]
    public void DecodeSingleSpanBatch()
    {
        const string hex = "01ed9ba1d004dfa9dca7d9f4b7d05a325769129a1e957104010f5823f7d7b58ec8837b875fe973d3d8979a7eee39aca4fa9664471afeaa040b0101010102045746257c828efe21288cf69cd26d023204b51d8d537c62efe2b15bf565e3caaf60208844230ec2c2503348c649a238dd231da0e35a7c8262da6db9f2fc727059ddc571acae7176133493fc8b26301d66f28f1e686ceebab9b0dbb96cceff39b95f4ab63b022dc43032971d21a84d913f45d097012e45ce8ee4ecd6bf9a7311a5d0a1d8e4b2d2742b728e73b2150fb812ee05718d5c0b42f384e44f6eb838d5305fe1fa882c10acace4adc48e9909ef358287ace7d7e25135b98e141554c59f6eaa6c610a13952045cf61f8f374692fb17142d292a16ad894fa3097a40e99415679f7980a587019d467f8f2da53068a5d29d6f437d77239d992fb1876dfa60b8e3a97ba8f68627d003851c72712e8d0d5a869f616a76fc24d4649325a236811710bd6ffe6c2d2cce40f8570abb559266670ddcbc3fc995326b2f981b9f9032e8853444835ec58000088743dc13203ffb2eab90319485515d488227c969b561a04d56bec5d080c18cb61178511068ef972f059c5c4e91f7025af950e43af9288534c4aa7358ec0a1c769cff1d7d3d0dc64d68c997cb2e0f86d8228ea806645a57a196f669e5a075de1144153dbdfd5392a50ab79b226cf2b4fe3a80270dc784874246d1eb2f0c3bb458f94ccf129d9b8b8a3ba5fb1cde16f5de7a214c718a84c5a8d75e00d13d8d658e7a3db5d4d06c172d0f582b31ebdd9485cabe8aaba2fd4dc56f737f10a182f4cb352d641b8ff13e3d2601796f036159222314a73d8d19b183a4389fa4a74b4c5028596eec95f7d8f17afac441f074a1b4da6689f8ab1532a1f90586bdedff0e6ebf70fe5d1c26ac977a3ae9696ea4bf8009e0ee073e800db98783eab20a69d1b38de60e6dc1c20759863f4e8150504ae02b89c040d83befba021da4ee7031a924af56448349105c8c8e6e2e2f424133e5b3cd87cafc1083867e5543bd5fe8f35083d0fab1c43c499d445e50dc1b81adfc9b6b4bb6f64884467c4877a65d50f4faa6ba9dd6c81e07f1ef4783ed5cfcf4bfafedb5917e6163b5b17a3adb9145d0c9c8f3d0ca24188b3db1787cdb35c06315ea5d91f7f3d7c80e03c6cc80199b7277962a0d345a952784443b6ea695ff4e3ea5ce12728e6237b5e5206a72b7933db4991fbeff815f6bdff37c0fe0d86acccbb8756c580805dc97fab68d5bd4b9fdcf0e869ad693e3f23510a3c471cb94aefedbac5cd61a227d2a86eff1dbbc89ab34c1dc7a3c0a934fc3b6f70ced9a4c05029d7a4273dcddc9998fb825b8f1a93e772b8a11e250405aac197b2b10d432154f12d46e5aaf83dd7a38c38f61bac02b8348ae983d8d6d2d10a7a71ec98564f015910bb077d9324c550a1440592bf9c1bdfe1635440c6aee23e755f222bcdb8067efc1b6527db2247bf224da6055588e3674a5c30a0521147743a7d89421b7cdc0a5bc9f718eab3ab38a5e1baebc04621513a5d00199cfa25ea946a107adbd453a904298eebc0e5760777a6051099fe94fe6151b4ff2f04a80113788a2f9eb2e26613aa32bb0267362805aa6c7e535fbd6612d6951ea5bdde84c05be2d902793c8bc01a4455215c371a74c2f8cfa3f35b7a0302e572f901e6886124fee993bc000088947902a97a7abf0bb901d15c5b0f5a62c90e175f998ee98115fa6ee1a0b9f708704902235345770e065ac4d3d43e6f66482b1f3488f38fbe158d2ed04f0d81a865bae80bd957d2fb1228fcc335afe1fc171ca17ff296415f2c7895a6ec3561bf71a34c40f2c6baf066ad4f41b5c89cecc91d44f517f1a0449ddc250873005a7f0cbca904b6176853218c63dd77758f2eeaced5da39a6ae2aaf9358c6268edfe91e7f161ba69a564fa81093b0c463b49bac1dad9c70df9c1622451a20c1c3ef225aed40f1db90d225eefe906a86938510267761d3fc518c11ab11f35e3f66feb784b8c8b84a2e3cd93bcf9c964a407a54bdcf9e594d81bab533cdcd659969543d75dbb2ce2411daccaf2675523a0f0f49bad0f26cc3cff853411f66c661a8ead90211081306838cc18c6e1aedb8df78f533a605edcbe4e24bd6404843d8b79c4a3cbb98c318378d990db39acb8154cecd1e5251bd258de852a2c5b4292a6bbce8383bb894e141ec80a78e51f1448850af993f18e5315c4cb4c8d397921608733a81370d7b803ba019a08ad75a25035f09ac53a89f3573282623b1e31d4829dafd3d801b04ca2d0aa2043e10bfe21619ec93fb3bddeac27f4a7ea969d6bf2a0563f3e7ed5df2e41f97308f21633b86fe4f44664cb65f225de096905a3601f90328880de0b6b3a764000088ce04f894f6dff6efb90312a1a85e158c277bebf76ffbdfbf0950af2a731471d53f18cdc3213621d648299a1309ec3fb66fcc871678003b370bd2c4f7763eb6ba56c525906496e979b20cbcd21254b44d7d3dea1d3b34d286e398b7529ff3a38b0b8ab7b9ab5fc9e3f04dd2f9a7ab7d9df3323f2211fb41352f03d4f74377df9621992ebfc376d6f85662e98e2fa440284bede4d4617a83cab8142b74dcd327b0177478bc4a156f557fb947ef45495b9041f86d2a247d5f1212a8b088ae5baa2b1dc7a829e0a3d2a0e766acb8a2a9bf674fd511756a8088843c2c8daabe10a652d44b546b9d0374e8daf3ead390f622ae286f0c664eecf567c415cf22e25aa69d8209444194c7d53aca10ad12d3f905a9511dca9445768063f18a08a6dcdb69e865ffcaff1f5a210c4b2bbbe4017eba33a0abe12cba2c99eced5dc42473ba6964dd58aebdb794d8203888c372c965c3b0bcc727e651823ea7d36e2c77378c6b00de06d640e5c87e0d2ff8d68585b56686a9d4ce02a00233e8181688f8a75f31803292942351c7156f0a6600a1ab2b206786969c33568d916cb1b404fa19d97b0e9b2e1fd282367d145777a2d451cbe94667b6025636caf49d4e37660467ca66cb2863c58254bf95023d36a4e3ebfe1294f95495a9348cd7f68bfd70a8368fb516a5bede14af5c98a3b0a61e95187eca74d09984c0ea8365aa8e0a870a9da1ad3049065ca20cf15799337366a915e12cca2cb5f3f557794dbc4bb0b66f6301fe0b07d06cbb58a610587813a116ad3a0262a2b167afb2919452acd26d2c4ca0b1cc54b0dcfb24017e1d5f86ae769664cdb327651ffcfcdd8108a798d50eaf2172e56d2737d318543e02f5575e3425dd8c5ad77dbbb3e196c0ab4a9f5a7e30b698819fbe95e66c608ba1eb70b3223c8654f44d04dd90a1e6e15b8f6b7d0f714b582f67584f59c49d497b34d8d084cf6d6b87937f198f50e79e4054f5a16f0d86e2dd2636c3aec9193a54d79f608bb5ebaef0240bee0fb35e4d5cc87602b99a45773d217265b402d8dc2c1eef10851a4163588f7c28b9548de8fab0db630e14bc491f28e7c61194c8e3a9490324e4c58116ba82b1f8ca2f9b3234964660a8aac002f9016e887ce66c50e2840000843b5fe25e881de9444cbf8902adb901536935889556d8bb9e1f1e1c86b95e9144bc217d86556dd8539836636b2eca8956273e84340455f1afda6bd16176d811af9848dc5b4b946de2d2b10bdb5324fca973a62bee5d229f479f1c425130d01ac2ef322b7cf99705f7cfef48351cf0f2c50ba6de1e5bcd9edfe4ac344b0be372c060f043ed199fd2a00514b123e1ae2be7e79f0119ac60de1da496fe88c8d92a42b28c2a82e349a920b2b2087d3a4489e76e976f22635ccde7c089bdf1cd72e2056ab45846f0ef7bcec83dff0ebc64dce6f9435b2df3a6a1d0312260b81b7a1e8c3f915d98d11785299447cdf9a8f0cc88710fa50ba02645e3cc520a72ef3789a9ee02a701f628ecf9c4d7a0d7dbfe5646e4bdda680c8a94b45be9172ccdbb5cb39a9f67bb423135ec529a1260a9512e710f74ea30b44b93c81d5bc33018d7b0cedbd26f1a77b9d6e8f9af80d88d0134996ea811bd226694be5f4660d063116d6718d349c0bdfbb6a5e2bdeaf8728d84a3fbf888e6f5df019cccdf8ad995c1c0e701a1b0da8c8fb89d853487f67a9ed107b3df14b5da6602";
        var expected = new BatchV1
        {
            RelTimestamp = 0x4a084ded,
            L1OriginNum = 0x5aa0dfa594f714df,
            ParentCheck = Bytes.FromHexString("0x325769129a1e957104010f5823f7d7b58ec8837b"),
            L1OriginCheck = Bytes.FromHexString("0x875fe973d3d8979a7eee39aca4fa9664471afeaa"),
            BlockCount = 0x4,
            OriginBits = 0b1011,
            BlockTxCounts = [1, 1, 1, 1],
            Txs = new BatchV1.Transactions
            {
                ContractCreationBits = 0b10,
                YParityBits = 0b100,
                Signatures = [
                    (UInt256.Parse("39475155842676302368188737273650790796571640545145087076759978442128892349103"), UInt256.Parse("43479513044538020905359337077180956350821082932750944182239461227016249045081")),
                    (UInt256.Parse("100309992961482241620367214489687302941692363726928579427712896587124482980281"), UInt256.Parse("43101725006905328352357026504806523924266536744633095889297909501784552051109")),
                    (UInt256.Parse("94367031825659639114638262573806307072536408933640156887692325710504989873456"), UInt256.Parse("43368990312765488073314007372955513081698797758528670610053912442926331699054")),
                    (UInt256.Parse("77084673483208737333939129111291106673862988021563372316274893567244444975446"), UInt256.Parse("55167315247933270060965483664848888923021317150624474513514356372989660236686")),
                ],
                Tos =
                [
                    new Address("0x3a97ba8f68627d003851c72712e8d0d5a869f616"),
                    new Address("0xa76fc24d4649325a236811710bd6ffe6c2d2cce4"),
                    new Address("0x0f8570abb559266670ddcbc3fc995326b2f981b9"),
                ],
                Datas = [
                    Bytes.FromHexString("0xf9032e8853444835ec58000088743dc13203ffb2eab90319485515d488227c969b561a04d56bec5d080c18cb61178511068ef972f059c5c4e91f7025af950e43af9288534c4aa7358ec0a1c769cff1d7d3d0dc64d68c997cb2e0f86d8228ea806645a57a196f669e5a075de1144153dbdfd5392a50ab79b226cf2b4fe3a80270dc784874246d1eb2f0c3bb458f94ccf129d9b8b8a3ba5fb1cde16f5de7a214c718a84c5a8d75e00d13d8d658e7a3db5d4d06c172d0f582b31ebdd9485cabe8aaba2fd4dc56f737f10a182f4cb352d641b8ff13e3d2601796f036159222314a73d8d19b183a4389fa4a74b4c5028596eec95f7d8f17afac441f074a1b4da6689f8ab1532a1f90586bdedff0e6ebf70fe5d1c26ac977a3ae9696ea4bf8009e0ee073e800db98783eab20a69d1b38de60e6dc1c20759863f4e8150504ae02b89c040d83befba021da4ee7031a924af56448349105c8c8e6e2e2f424133e5b3cd87cafc1083867e5543bd5fe8f35083d0fab1c43c499d445e50dc1b81adfc9b6b4bb6f64884467c4877a65d50f4faa6ba9dd6c81e07f1ef4783ed5cfcf4bfafedb5917e6163b5b17a3adb9145d0c9c8f3d0ca24188b3db1787cdb35c06315ea5d91f7f3d7c80e03c6cc80199b7277962a0d345a952784443b6ea695ff4e3ea5ce12728e6237b5e5206a72b7933db4991fbeff815f6bdff37c0fe0d86acccbb8756c580805dc97fab68d5bd4b9fdcf0e869ad693e3f23510a3c471cb94aefedbac5cd61a227d2a86eff1dbbc89ab34c1dc7a3c0a934fc3b6f70ced9a4c05029d7a4273dcddc9998fb825b8f1a93e772b8a11e250405aac197b2b10d432154f12d46e5aaf83dd7a38c38f61bac02b8348ae983d8d6d2d10a7a71ec98564f015910bb077d9324c550a1440592bf9c1bdfe1635440c6aee23e755f222bcdb8067efc1b6527db2247bf224da6055588e3674a5c30a0521147743a7d89421b7cdc0a5bc9f718eab3ab38a5e1baebc04621513a5d00199cfa25ea946a107adbd453a904298eebc0e5760777a6051099fe94fe6151b4ff2f04a80113788a2f9eb2e26613aa32bb0267362805aa6c7e535fbd6612d6951ea5bdde84c05be2d902793c8bc01a4455215c371a74c2f8cfa3f35b7a0302e572"),
                    Bytes.FromHexString("0xf901e6886124fee993bc000088947902a97a7abf0bb901d15c5b0f5a62c90e175f998ee98115fa6ee1a0b9f708704902235345770e065ac4d3d43e6f66482b1f3488f38fbe158d2ed04f0d81a865bae80bd957d2fb1228fcc335afe1fc171ca17ff296415f2c7895a6ec3561bf71a34c40f2c6baf066ad4f41b5c89cecc91d44f517f1a0449ddc250873005a7f0cbca904b6176853218c63dd77758f2eeaced5da39a6ae2aaf9358c6268edfe91e7f161ba69a564fa81093b0c463b49bac1dad9c70df9c1622451a20c1c3ef225aed40f1db90d225eefe906a86938510267761d3fc518c11ab11f35e3f66feb784b8c8b84a2e3cd93bcf9c964a407a54bdcf9e594d81bab533cdcd659969543d75dbb2ce2411daccaf2675523a0f0f49bad0f26cc3cff853411f66c661a8ead90211081306838cc18c6e1aedb8df78f533a605edcbe4e24bd6404843d8b79c4a3cbb98c318378d990db39acb8154cecd1e5251bd258de852a2c5b4292a6bbce8383bb894e141ec80a78e51f1448850af993f18e5315c4cb4c8d397921608733a81370d7b803ba019a08ad75a25035f09ac53a89f3573282623b1e31d4829dafd3d801b04ca2d0aa2043e10bfe21619ec93fb3bddeac27f4a7ea969d6bf2a0563f3e7ed5df2e41f97308f21633b86fe4f44664cb65f225de096905a36"),
                    Bytes.FromHexString("0xf90328880de0b6b3a764000088ce04f894f6dff6efb90312a1a85e158c277bebf76ffbdfbf0950af2a731471d53f18cdc3213621d648299a1309ec3fb66fcc871678003b370bd2c4f7763eb6ba56c525906496e979b20cbcd21254b44d7d3dea1d3b34d286e398b7529ff3a38b0b8ab7b9ab5fc9e3f04dd2f9a7ab7d9df3323f2211fb41352f03d4f74377df9621992ebfc376d6f85662e98e2fa440284bede4d4617a83cab8142b74dcd327b0177478bc4a156f557fb947ef45495b9041f86d2a247d5f1212a8b088ae5baa2b1dc7a829e0a3d2a0e766acb8a2a9bf674fd511756a8088843c2c8daabe10a652d44b546b9d0374e8daf3ead390f622ae286f0c664eecf567c415cf22e25aa69d8209444194c7d53aca10ad12d3f905a9511dca9445768063f18a08a6dcdb69e865ffcaff1f5a210c4b2bbbe4017eba33a0abe12cba2c99eced5dc42473ba6964dd58aebdb794d8203888c372c965c3b0bcc727e651823ea7d36e2c77378c6b00de06d640e5c87e0d2ff8d68585b56686a9d4ce02a00233e8181688f8a75f31803292942351c7156f0a6600a1ab2b206786969c33568d916cb1b404fa19d97b0e9b2e1fd282367d145777a2d451cbe94667b6025636caf49d4e37660467ca66cb2863c58254bf95023d36a4e3ebfe1294f95495a9348cd7f68bfd70a8368fb516a5bede14af5c98a3b0a61e95187eca74d09984c0ea8365aa8e0a870a9da1ad3049065ca20cf15799337366a915e12cca2cb5f3f557794dbc4bb0b66f6301fe0b07d06cbb58a610587813a116ad3a0262a2b167afb2919452acd26d2c4ca0b1cc54b0dcfb24017e1d5f86ae769664cdb327651ffcfcdd8108a798d50eaf2172e56d2737d318543e02f5575e3425dd8c5ad77dbbb3e196c0ab4a9f5a7e30b698819fbe95e66c608ba1eb70b3223c8654f44d04dd90a1e6e15b8f6b7d0f714b582f67584f59c49d497b34d8d084cf6d6b87937f198f50e79e4054f5a16f0d86e2dd2636c3aec9193a54d79f608bb5ebaef0240bee0fb35e4d5cc87602b99a45773d217265b402d8dc2c1eef10851a4163588f7c28b9548de8fab0db630e14bc491f28e7c61194c8e3a9490324e4c58116ba82b1f8ca2f9b3234964660a8aac0"),
                    Bytes.FromHexString("0xf9016e887ce66c50e2840000843b5fe25e881de9444cbf8902adb901536935889556d8bb9e1f1e1c86b95e9144bc217d86556dd8539836636b2eca8956273e84340455f1afda6bd16176d811af9848dc5b4b946de2d2b10bdb5324fca973a62bee5d229f479f1c425130d01ac2ef322b7cf99705f7cfef48351cf0f2c50ba6de1e5bcd9edfe4ac344b0be372c060f043ed199fd2a00514b123e1ae2be7e79f0119ac60de1da496fe88c8d92a42b28c2a82e349a920b2b2087d3a4489e76e976f22635ccde7c089bdf1cd72e2056ab45846f0ef7bcec83dff0ebc64dce6f9435b2df3a6a1d0312260b81b7a1e8c3f915d98d11785299447cdf9a8f0cc88710fa50ba02645e3cc520a72ef3789a9ee02a701f628ecf9c4d7a0d7dbfe5646e4bdda680c8a94b45be9172ccdbb5cb39a9f67bb423135ec529a1260a9512e710f74ea30b44b93c81d5bc33018d7b0cedbd26f1a77b9d6e8f9af80d88d0134996ea811bd226694be5f4660d063116d6718d349c0"),

                ],
                Types = [TxType.Legacy, TxType.Legacy, TxType.AccessList, TxType.EIP1559],
                TotalLegacyTxCount = 2,
                Nonces = [8282588029993729469, 16135157523101041165, 16681619638271338012, 3749939111286708257],
                Gases = [2013959, 125086, 339891, 1682741],
                ProtectedBits = 0b10,
            }
        };

        var bytes = Bytes.FromHexString(hex);
        var decoded = BatchDecoder.DecodeSpanBatches(bytes).ToList();

        decoded.Count.Should().Be(1);
        decoded[0].Should().BeEquivalentTo(expected, options => options
            .Using((IEqualityComparer<ReadOnlyMemory<byte>>)new MemoryContentsComparer<byte>()));
    }
}
